#include <vector>

#include <boost\numeric\interval.hpp>

#include <gmpxx.h>

#include "../predicates.h"

class convex_hull_iterator: public std::iterator<std::forward_iterator_tag, point>
{
    void init_intervals(const std::vector<point>::iterator&, boost::numeric::interval<double>&, boost::numeric::interval<double>&, void (*coord)(const point&, const point&, boost::numeric::interval<double>&));
    void init_mpqs(const std::vector<point>::iterator& it, mpq_class& mpq1, mpq_class& mpq2, void (*coord)(const point&, const point&, mpq_class&));

    bool can_go_left(const std::vector<point>::iterator&);
    bool can_go_right(const std::vector<point>::iterator&);
    bool can_go_up(const std::vector<point>::iterator&);

    point vect;
    std::vector<point>::iterator first_vertex, convex_hull, leftmost_it, uppermost_it, rightmost_it;

    std::reverse_iterator<std::vector<point>::iterator> current;
    std::reverse_iterator<std::vector<point>::iterator> first_vertex_ri;

    double area;
public:
    convex_hull_iterator(const std::reverse_iterator<std::vector<point>::iterator>&);
    convex_hull_iterator(const std::reverse_iterator<std::vector<point>::iterator>&, const std::vector<point>::iterator&, const std::vector<point>::iterator&, const std::reverse_iterator<std::vector<point>::iterator>&);

    friend std::ostream& operator <<(std::ostream& output, const convex_hull_iterator& it)
    {
        output << it.area;

        return output;
    }

    const double operator*() const;
    convex_hull_iterator& operator++();

    bool operator!=(const convex_hull_iterator&) const;
    bool operator==(const convex_hull_iterator&) const;
};